//
//  SwiftGrammarViewController.swift
//  DemoProject
//
//  Created by hao on 2018/7/19.
//  Copyright © 2018年 hao. All rights reserved.
//

/** static 与 class 的区别
 static 可以在类、结构体、或者枚举中使用。而 class 只能在类中使用。
 static 可以修饰存储属性，static 修饰的存储属性称为静态变量(常量)。而 class 不能修饰存储属性。
 static 修饰的计算属性不能被重写。而 class 修饰的可以被重写。
 static 修饰的静态方法不能被重写。而 class 修饰的类方法可以被重写。
 class 修饰的计算属性被重写时，可以使用 static 让其变为静态属性。
 class 修饰的类方法被重写时，可以使用 static 让方法变为静态方法。
 */

import UIKit

fileprivate enum GrammarEnumT {
    case Left
    case Right
    
    func descr() -> String {
        switch self {
        case .Left:
            return "左"
        case .Right:
            return "右"
        }
    }
}

class SwiftGrammarViewController: BaseViewController {
    
    let titlesArr = ["RxSwift之 Observable",
                     "RxSwift之 观察者",
                     "RxSwift之 Subjects",
                     "RxSwift之 操作符",
                     "RxSwift之 错误和调试操作",
                     "RxSwift之 序列、调度器",
                     "RxSwift之 双向绑定：<->",
                     "RxSwift之 URLSession",
                     "RxSwift之 上传下载",
                     "RxSwift之 RxMoya数据请求",
                     "RxSwift之 注册Demo"]
    
    let classArr = [RxSwiftObservableViewController.self,
                    RxSwiftBinderObserverViewController.self,
                    RxSwiftSubjectsViewController.self,
                    RxSwiftOperatorsViewController.self,
                    RxSwiftErrorDebugViewController.self,
                    RxSwiftSequenceViewController.self,
                    TwowayBindViewController.self,
                    RxURLSessionViewController.self,
                    RxFileUploadDownloadViewController.self,
                    RxMoyaRequestViewController.self,
                    RxRegisterDemoViewController.self]
    
    lazy var tableView: UITableView = {
        let _tableview = UITableView(frame: CGRect.zero, style: .plain)
        self.view.addSubview(_tableview)
        _tableview.delegate = self
        _tableview.dataSource = self
        return _tableview
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        intervalOperator()
        testExtensionSubscript()
        testEnum()
        testExtensionProcotol()
        automaticallyAdjustsScrollViewInsets = false
        self.tableView.snp.makeConstraints { (make) in
            make.left.right.bottom.equalTo(0)
            make.top.equalTo(kStatusBarAndNaviHeight())
        }
    }
    
    func testEnum() {
        let desc = GrammarEnumT.Left
        print(info: desc.descr())
        // 浮点数四舍五入转为整数
        lroundf(0.56)
    }
    
    /** 字典的创建 */
    private func dictSetup() {
        /** 通过元组创建字典 */
        let tupleArray = [("Monday", 30),  ("Tuesday", 25),  ("Wednesday", 27)]
        print(Dictionary(uniqueKeysWithValues: tupleArray)) //["Monday": 30, "Tuesday": 25, "Wednesday": 27]
        
        /** 通过键值序列创建字典 */
        let names = ["Apple", "Pear"]
        let prices = [7, 6]
        print(info: Dictionary(uniqueKeysWithValues: zip(names, prices))) //["Pear": 6,  "Apple": 7]
        
        /** 只有键序列、或者值序列创建字典 */
        let array = ["Monday", "Tuesday", "Wednesday"]
        let dict1 = Dictionary(uniqueKeysWithValues: zip(1..., array))
        let dict2 = Dictionary(uniqueKeysWithValues: zip(array, 1...))
        print("dict1：\(dict1)") // ["Monday" : 1, "Tuesday" : 2, "Wednesday" : 3]
        print("dict2：\(dict2)") // [1 : "Monday", 2 : "Tuesday", 3 : "Wednesday"]
        
        /** 字典分组（比如下面生成一个以首字母分组的字典） */
        let names2 = ["Apple", "Pear", "Grape", "Peach"]
        let dict = Dictionary(grouping: names2) { $0.first! }
        print(dict) //["P": ["Pear", "Peach"], "G": ["Grape"], "A": ["Apple"]]
    }
    
    private func aaaaaa() {
        /** swift自动为闭包提供参数名缩写功能，可以直接通过$0和$1表示闭包中的第一个第二个参数 */
        (1...10).sorted(by: {$1 < $0}).forEach {
            print(info: $0)
        }
        print(info: "-------------上下结果一致---------------")
        (1...10).sorted { (a, b) -> Bool in
            return b < a
        }.forEach { (i) in
            print(info: i)
        }
    }
    
    func bbbbbb() {
        let decimalInteger = 17
        let binaryInteger = 0b10001 + decimalInteger      // 二进制的17
        let octalInteger = 0o21 + binaryInteger           // 八进制的17
        let hexadecimalInteger = 0x11 + octalInteger      // 十六进制的17
        print(info: hexadecimalInteger)
    }
    
    private func testExtensionProcotol() {
        print(info: "简单模拟RxSwift扩展协议方式 -> \("HAO".ch.test)")
    }

}

// MARK: 测试 Extension Procotol
fileprivate struct CHReactive<T> {
    public let type: T
    public init(_ type: T) { self.type = type }
}
/// where 后面紧跟的是条件 T : NSString(或T == String) 表示 泛型 T 必须是 NSString(class类型) 的子类 或者 T == String(struct类型)
/// class类型使用  :
/// struct类型使用 ==
/// T 为 CHReactive 的泛型
fileprivate extension CHReactive where T == String {
    var test: String {
        return self.type + " TEST"
    }
}

fileprivate protocol CHReactiveCompatible {
    /// Extended type
    associatedtype CompatibleType
    /// Reactive extensions.
    var ch: CHReactive<CompatibleType> { get set }
}
fileprivate extension CHReactiveCompatible {
    /// Reactive extensions.
    var ch: CHReactive<Self> {
        get {
            return CHReactive(self)
        }
        set {
            // this enables using Reactive to "mutate" base object
        }
    }
}

extension String : CHReactiveCompatible {}
// MARK:

// MARK: 函数定义
extension SwiftGrammarViewController {
    
    func mapFunc<T>(values: [T], funcName: (T) -> ()) {
        values.forEach { (value) in
            funcName(value)
        }
    }
    
    /** 返回多个值组成的元组 */
    func test(name: String) -> (Int, Bool) {
        let position = 1
        let visible = false
        return (position, visible)
    }
    
    /** 可变形参：可以接受0个或者任意数量的输入参数 */
    func test1(numbers: Int...) -> Int {
        var count:Int = 0
        for number in numbers{
            count += number
        }
        return count
    }
    
    /** 同时改变函数内外的参数值，使用inout关键字，调用方式 add(age: &arg) */
    func add(age: inout Int) {
        age += 1
    }
    
    /** 参数为函数类型 */
    func printAdditiveResult(addFun: (Int) -> Int, a:Int) {
        print("Result:\(addFun(a))")
    }
    
    /** 返回值为函数类型 */
    func chooseFunction(backwards: Bool) -> (Int) -> Int {
        return backwards ? increase : reduce
    }
    func increase(input: Int) -> Int {
        return input + 1
    }
    func reduce(input: Int) -> Int {
        return input - 1
    }
    
}

// MARK: 区间运算符
extension SwiftGrammarViewController {
    
    fileprivate func intervalOperator() {
        let testStr = "Hao.com"
        print(info: "字母大写: \(testStr.uppercased())")
        print(info: "字母小写: \(testStr.lowercased())")
        print(info: "首字母大写: \(testStr.capitalized)")
        
        print(info: "startIndex: \(testStr.startIndex)")
        
        /**
         *   闭区间运算符：a...b
         *   半闭区间运算符：a..<b
         *   倒序循环 (0...10).reversed()
         */
        for i in (0...10).reversed() {
            print(info: "倒序 i = \(i)")
        }
        // 未使用区间运算符
        let index1 = testStr.index(testStr.startIndex, offsetBy: 1)
        let index2 = testStr.index(testStr.startIndex, offsetBy: 4)
        let range1 = Range(uncheckedBounds: (lower: index1, upper: index2))
        // swift3 的写法
//        let rangeStr = testStr.substring(with: range1)
        let rangeStr = testStr[range1]
        print(info: "range substring: \(rangeStr)")
        
        /**
         使用区间运算符 (不能使用封闭区间即 ‘...’)
         Swift 4:
            let newStr = String(str[..<index])
            let newStr = String(str[index...])
         */
        let range2 = index1 ..< index2
        // swift3 的写法
//        let rangeStr2 = testStr.substring(with: range2)
//        print(info: "range substring: \(rangeStr2)")
        
        _ = testStr[range2]
        
        /** 创建一个字符区间 */
        let interval = "a"..."z"
        testStr.forEach { (c) in
            if !interval.contains(String(c)) {
                print(info: "\(c)不是小写字母")
            }
        }
    }
    
    /** 测试自定义扩展下标 */
    fileprivate func testExtensionSubscript() {
        var str = "hao.chen.com"
        print(info: str[2, 4])
        print(info: str[5])
        
        // 替换
        str[3, 6] = "NEW"
        str[0] = "YX"
        print(info: str[0, str.count])
    }
    
}

// MARK: String扩展 (自定义下标: subscript, 调用方式 stringobj[0,3])
extension String {
    
    subscript(start:Int, length:Int) -> String
    {
        get{
            let index1 = self.index(self.startIndex, offsetBy: start)
            let index2 = self.index(index1, offsetBy: length)
            return String(self[index1..<index2])
        }
        set{
            let tmp = self
            var s = ""
            var e = ""
            // idx: 下标  item: 值
            for (idx, item) in tmp.enumerated() {
                if idx < start {
                    s += "\(item)"
                }
                if idx >= start + length {
                    e += "\(item)"
                }
            }
            self = s + newValue + e
        }
    }
    
    subscript(index:Int) -> String {
        get{
            return String(self[self.index(self.startIndex, offsetBy: index)])
        }
        set{
            let tmp = self
            self = ""
            for (idx, item) in tmp.enumerated() {
                if idx == index {
                    self += "\(newValue)"
                } else {
                    self += "\(item)"
                }
            }
        }
    }
    
}


extension SwiftGrammarViewController : UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return titlesArr.count
    }
    
    static let Identifier = "SwiftGrammarCellIdentifier"
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell = tableView.dequeueReusableCell(withIdentifier: SwiftGrammarViewController.Identifier)
        if cell == nil {
            cell = UITableViewCell(style: .value1, reuseIdentifier: SwiftGrammarViewController.Identifier)
            cell?.accessoryType = .disclosureIndicator
        }
        cell?.textLabel?.text = self.titlesArr[indexPath.row]
        return cell!
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        let clazzType = self.classArr[indexPath.row]
        var controller: UIViewController!
//        let controller = self.classArr[indexPath.row].init()
        if clazzType is RxRegisterDemoViewController.Type {
            controller = RxRegisterDemoViewController(nibName: "RxRegisterDemoViewController", bundle: nil)
        } else {
            controller = clazzType.init()
        }
        controller.navigationItem.title = self.titlesArr[indexPath.row]
        self.navigationController?.pushViewController(controller, animated: true)
    }
    
}







